//
// loadShader
//
// 'shaderId' is the id of a <script> element containing the shader source string.
// Load this shader and return the WebGLShader object corresponding to it.
//
function loadShader(ctx, shaderId)
{
	var shaderScript = document.getElementById(shaderId);
	if (!shaderScript) {
		log("*** Error: shader script '"+shaderId+"' not found");
		return null;
	}

	if (shaderScript.type == "x-shader/x-vertex")
		var shaderType = ctx.VERTEX_SHADER;
	else if (shaderScript.type == "x-shader/x-fragment")
		var shaderType = ctx.FRAGMENT_SHADER;
	else {
		log("*** Error: shader script '"+shaderId+"' of undefined type '"+shaderScript.type+"'");
		return null;
	}

	// Create the shader object
	var shader = ctx.createShader(shaderType);

	// Load the shader source
	ctx.shaderSource(shader, shaderScript.text);

	// Compile the shader
	ctx.compileShader(shader);

	// Check the compile status
	var compiled = ctx.getShaderParameter(shader, ctx.COMPILE_STATUS);
	if (!compiled && !ctx.isContextLost()) {
		// Something went wrong during compilation; get the error
		var error = ctx.getShaderInfoLog(shader);
		log("*** Error compiling shader '"+shaderId+"':"+error);
		ctx.deleteShader(shader);
		return null;
	}

	return shader;
}

//
// makeBox
//
// Create a box with vertices, normals and texCoords. Create VBOs for each as well as the index array.
// Return an object with the following properties:
//
//  vertexObject        WebGLBuffer object for vertices
//
function makeBox(ctx)
{

	// vertex coords array
	var vertices = new Float32Array(
		[  
		 0.5, -0.5,  0.5,  0.5,  0.5, -0.5,  0.5,  0.5,  0.5, 
		 0.5,  0.5, -0.5,  0.5, -0.5,  0.5,  0.5, -0.5, -0.5, 
		-0.5, -0.5, -0.5, -0.5,  0.5,  0.5, -0.5,  0.5, -0.5, 
		-0.5,  0.5,  0.5, -0.5, -0.5, -0.5, -0.5, -0.5,  0.5, 
		-0.5, -0.5, -0.5,  0.5,  0.5, -0.5,  0.5, -0.5, -0.5, 
		 0.5,  0.5, -0.5, -0.5, -0.5, -0.5, -0.5,  0.5, -0.5, 
		-0.5,  0.5,  0.5,  0.5, -0.5,  0.5,  0.5,  0.5,  0.5, 
		 0.5, -0.5,  0.5, -0.5,  0.5,  0.5, -0.5, -0.5,  0.5, 
		 0.5,  0.5, -0.5, -0.5,  0.5,  0.5,  0.5,  0.5,  0.5, 
		-0.5,  0.5,  0.5,  0.5,  0.5, -0.5, -0.5,  0.5, -0.5,
		-0.5, -0.5, -0.5,  0.5, -0.5,  0.5, -0.5, -0.5,  0.5, 
		 0.5, -0.5,  0.5, -0.5, -0.5, -0.5,  0.5, -0.5, -0.5  ]   
	);


	var retval = { };

	retval.vertexObject = ctx.createBuffer();
	ctx.bindBuffer(ctx.ARRAY_BUFFER, retval.vertexObject);
	ctx.bufferData(ctx.ARRAY_BUFFER, vertices, ctx.STATIC_DRAW);

	ctx.bindBuffer(ctx.ARRAY_BUFFER, null);

	retval.numPoints = vertices.length/3;
	
	return retval;
}

//
// loadImageTexture
//
// Load the image at the passed url, place it in a new WebGLTexture object and return the WebGLTexture.
//
// Array of images curently loading
var g_loadingImages = [];

function loadImageTexture(ctx, url)
{
	var texture = ctx.createTexture();
	var image = new Image();
	g_loadingImages.push(image);
	image.onload = function() { doLoadImageTexture(ctx, image, texture) }
	image.src = url;
	return texture;
}

function doLoadImageTexture(ctx, image, texture)
{
	g_loadingImages.splice(g_loadingImages.indexOf(image), 1);
	ctx.bindTexture(ctx.TEXTURE_2D, texture);
	ctx.texImage2D(
		ctx.TEXTURE_2D, 0, ctx.RGBA, ctx.RGBA, ctx.UNSIGNED_BYTE, image);
	ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_MAG_FILTER, ctx.LINEAR);
	ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_MIN_FILTER, ctx.LINEAR);
	//ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_WRAP_S, ctx.CLAMP_TO_EDGE);
	//ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_WRAP_T, ctx.CLAMP_TO_EDGE);
	//ctx.generateMipmap(ctx.TEXTURE_2D)
	ctx.bindTexture(ctx.TEXTURE_2D, null);
}
//
// Framerate object
//
// This object keeps track of framerate and displays it as the innerHTML text of the
// HTML element with the passed id. Once created you call snapshot at the end
// of every rendering cycle. Every 500ms the framerate is updated in the HTML element.
//
Framerate = function(id)
{
    this.numFramerates = 10;
    this.framerateUpdateInterval = 500;
    this.id = id;

    this.renderTime = -1;
    this.framerates = [ ];
    self = this;
    var fr = function() { self.updateFramerate() }
    setInterval(fr, this.framerateUpdateInterval);
}

Framerate.prototype.updateFramerate = function()
{
    var tot = 0;
    for (var i = 0; i < this.framerates.length; ++i)
        tot += this.framerates[i];

    var framerate = tot / this.framerates.length;
    framerate = Math.round(framerate);
    document.getElementById(this.id).innerHTML = "Framerate:"+framerate+"fps";
}

Framerate.prototype.snapshot = function()
{
    if (this.renderTime < 0)
        this.renderTime = new Date().getTime();
    else {
        var newTime = new Date().getTime();
        var t = newTime - this.renderTime;
        if (t == 0)
            return;
        var framerate = 1000/t;
        this.framerates.push(framerate);
        while (this.framerates.length > this.numFramerates)
            this.framerates.shift();
        this.renderTime = newTime;
    }
}
